<template>
  <div class="content-container">

    <h3>服务器物理文件</h3>
    <p>目录可以展开，文件可以下载</p>
    <div v-if="files.length <= 0">
      <el-empty description="什么资源都看不到"></el-empty>
    </div>
    <div>
      <!-- 面包屑：当前所在目录 -->
      <el-breadcrumb separator="\" v-show="resourceRootDir">
        <el-breadcrumb-item v-for="(path, index) in currentDirArr" :key="index">
          <button @click="breadcrumbClickHandle(index)" :disabled="disabledBreadcrumbItemByItsIndex(index)">
            {{ path }}
          </button>
        </el-breadcrumb-item>
      </el-breadcrumb>

      <!-- 文件列表 -->
      <ul v-show="resourceRootDir">
        <!-- 固定项：返回上级 -->
        <li>
          <span title="返回上级目录" class="el-icon-folder-opened" @click="backToParentDirectory">../</span>
        </li>
        <!-- 动态项：文件夹或文件 -->
        <li v-for="f in files" :key="f.fullName">
          <span :class="bindItemClassByType(f.directoryOrNot)" @click="breadcrumbItemClickHandle(f)"
            :title="f.absolutePath">
            {{ f.fullName }}
          </span>
        </li>
      </ul>
    </div>

  </div>
</template>

<script>
import { mapGetters } from 'vuex'
export default {

  data() {
    return {
      resourceRootDir: '',
      files: []
    }
  },

  computed: {
    // 借助生成计算属性：uiAuthValidateIsNotNeeded、servePhysicFileAuths
    ...mapGetters('uiAuthModule', ['uiAuthValidateIsNotNeeded', 'servePhysicFileAuths']),
    // 各个操作可用性
    directoryBackwardsStatus() {
      const { directoryBackwards: { finalStatus } } = this.servePhysicFileAuths
      return this.uiAuthValidateIsNotNeeded || finalStatus
    },
    directoryForwardsStatus() {
      const { directoryForwards: { finalStatus } } = this.servePhysicFileAuths
      return this.uiAuthValidateIsNotNeeded || finalStatus
    },
    fileDownloadStatus() {
      const { fileDownload: { finalStatus } } = this.servePhysicFileAuths
      return this.uiAuthValidateIsNotNeeded || finalStatus
    },
    getVisitableRootDirectoryStatus() {
      const { getVisitableRootDirectory: { finalStatus } } = this.servePhysicFileAuths
      return this.uiAuthValidateIsNotNeeded || finalStatus
    },

    // 当前文件所在的目录分割成数组
    currentDirArr() {
      let curAbsolutePathArr = []
      // 若文件列表不为空数组
      if (this.files && this.files.length > 0) {
        curAbsolutePathArr = this.files[0].absolutePath.split('\\')
        // 去掉文件名，得到文件所在目录
        curAbsolutePathArr.pop()
      } else {
        curAbsolutePathArr = this.resourceRootDirArr
      }
      return curAbsolutePathArr
    },

    // 可访问资源根目录分割为数组
    resourceRootDirArr() {
      return this.resourceRootDir.split('\\')
    }
  },

  methods: {
    // 面包屑动态数据部分点击处理
    breadcrumbClickHandle(index) {
      const currDirArr = this.currentDirArr
      // 若重复点击当前目录，提示并返回
      if (index === currDirArr.length - 1) {
        this.$message.warning("已处于该目录")
        return
      }
      // 若访问的范围超过跟路径，提示并返回
      if (index < this.resourceRootDirArr.length - 1) {
        this.$message.error("无法访问！")
        return
      }
      // 计算出栈次数(当前目录的元素个数 - 面包屑索引 - 1)
      const popCount = currDirArr.length - index - 1
      for (let i = 0; i < popCount; i++) {
        // 去掉当前索引后面的
        currDirArr.pop()
      }

      // 目标目录数组
      const targetDirArr = currDirArr
      this.expandChildrenOfDirectory(targetDirArr.join('\\'))
    },

    // 初始化可访问的资源根目录
    async initVisibilityResourceRootDir() {
      const { data: response } = await this.$axios.get('/admin/file/visibilityOfResourceRoot')
      if (response.code === 0) {
        this.$message.error(response.msg)
        return
      }
      this.resourceRootDir = response.data
      this.expandChildrenOfDirectory(this.resourceRootDir)
    },

    // 返回当前目录的父目录
    async backToParentDirectory() {
      let curDirArr = this.currentDirArr
      // 若再次访问的目录为根目录，直接返回
      if (this.resourceRootDir === curDirArr.join("\\")) {
        this.$message.warning('无法再继续访问上级目录了~')
        return
      }
      try {
        // 否则获取数据
        const { data: response } = await this.$axios({
          url: '/admin/file/returnParentDirOfCurDir',
          params: {
            specificFile: this.files[0].absolutePath
          }
        })
        // 更新当前文件信息
        this.files = response.data
      } catch (error) {
        console.log(error)
      }
    },

    // 展开指定目录的直接子文件列表
    async expandChildrenOfDirectory(dirAbsolutePath) {
      try {
        const { data: response } = await this.$axios({
          url: '/admin/file/childrenOfDir',
          params: {
            dirAbsolutePath: dirAbsolutePath
          }
        })
        if (response.code === 0) {
          this.$message.error(response.msg)
          return
        }
        // 更新文件列表
        this.files = response.data
      } catch (error) {
        console.log(error)
      }
    },

    // 下载指定文件到磁盘（浏览器指定的文件下载位置）
    async downloadFile(file) {
      try {
        await this.$confirm(`确定下载 ${file.fullName} 吗?`)
        // 获取文件数据
        const response = await this.$axios({
          url: '/admin/file',
          params: { absolutePath: file.absolutePath, },
          responseType: 'arraybuffer',
        })
        // 通过创建a标签保存文件数据到磁盘
        const link = document.createElement('a')
        link.style.display = 'none'
        link.href = response.request.responseURL
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
      } catch (error) {
        console.dir(error)
      }
    },

    // 根据面包屑条目对应的索引，决定是否将其自身禁用
    disabledBreadcrumbItemByItsIndex(index) {
      return index < this.resourceRootDirArr.length - 1
    },

    // 面包屑动态项点击分类处理
    breadcrumbItemClickHandle(file) {
      // 若为目录，将其展开
      if (file.directoryOrNot) {
        this.expandChildrenOfDirectory(file.absolutePath)
      }
      // 若为文件，下载
      else {
        this.downloadFile(file)
      }
    },

    // 绑定动态项的类名，为目录和文件添加不同图标，以示区别
    bindItemClassByType(isDirectory) {
      if (isDirectory) {
        return 'el-icon-folder'
      }
      else {
        return 'el-icon-document'
      }
    }
  },

  mounted() {
    // 如果具有访问根路径的权限
    if (this.getVisitableRootDirectoryStatus) {
      this.initVisibilityResourceRootDir()
    }
  }
}
</script>

<style lang="less" scoped>
.content-container {
  width: 90%;
  margin: 0 auto;

  ul {
    list-style: none;
    padding: 0px;
    border-left: 1px solid #000;
    padding-left: 10px;
  }

  ul li {
    display: block;
    padding: 5px 0px 5px 0px;
  }

  ul li:nth-child(1) span {
    color: #409eff;
  }

  ul li span {
    padding: 2px;
  }
}
</style>